import re

from django.conf import settings
from django.utils.deprecation import MiddlewareMixin


def add_menu_class(menu_dict, parent_id, breadcrumbs):
    """
    把所有父节点全部添加class属性并设置为active
    :param menu_dict: 树形菜单字典
    :param parent_id: 父菜单id
    :param breadcrumbs: 面包屑导航
    :return:
    """
    node = menu_dict.get(parent_id)
    # 点击菜单索引加入点击激活列表
    menu_dict["active"].append(parent_id)
    # 获取父菜单id
    node_parent_id = node.get("parent")
    # 如果有父菜单id， 递归本函数，直到所有父节点都含有class属性并且设置为active
    if node_parent_id:
        add_menu_class(menu_dict, node_parent_id, breadcrumbs)
    # 递归后添加，每次都是从根菜单到叶子菜单，从上到下顺序添加
    breadcrumbs.append({"title": node["title"], "url": node["url"], "class": None, })


class MenuMiddleware(MiddlewareMixin):
    """
    菜单信息处理
    """

    def process_request(self, request):
        """
        当用户请求进来触发执行
        :param request:
        :return:
        """
        # 面包屑导航定义
        breadcrumbs = [{"title": "首页", "url": "/", "class": None, }, ]
        # 获取原始menu数据
        menu_dict = request.session.get(settings.MENU_SESSION_KEY)
        api_num = 0
        if menu_dict:
            # 首先把已点击菜单清空
            menu_dict["active"] = list()
            # 获取当前用户请求的url
            current_url = request.path_info

            # 获取菜单字典的所有值
            for key in menu_dict:
                # 如果key是数字，说明不是自定义的值
                if key.isdigit():
                    # 获得url
                    url = menu_dict[key]['url']
                    # 获取api的key值，在显示的时候去除 api 的显示
                    if menu_dict[key].get("title") == "api":
                        api_num = key
                # 自定义值，比如root等
                else:
                    continue
                # 判断匹配
                reg = f"^{url}$"
                if re.match(reg, current_url):
                    # 如果匹配成功判断是叶子菜单还是内部菜单，执行动作不一样
                    # 是内部节点
                    if "inner_parent" in menu_dict[key]:
                        inner_menu = menu_dict[key]
                        add_menu_class(menu_dict, inner_menu['inner_parent'], breadcrumbs)
                    # 如果是非顶级菜单的叶子菜单节点
                    elif "parent" in menu_dict[key]:
                        leaf_menu = menu_dict[key]
                        # 当前节点也要设置class属性，并且设置为active
                        menu_dict["active"].append(key)
                        add_menu_class(menu_dict, leaf_menu['parent'], breadcrumbs)
                    # 即不是内部节点也不是叶子节点
                    # 说明是顶级节点，并且自己就是叶子节点了
                    else:
                        menu_dict["active"].append(key)
                    # 当前节点为操作节点，添加到导航最后
                    breadcrumbs.append(
                        {"title": menu_dict[key]["title"], "url": menu_dict[key]["url"], "class": "active", })
                    break
        request.o_menu = menu_dict
        # 不显示 api 项，只影响菜单显示，不影响权限的菜单字典
        if request.o_menu and int(api_num) != 0:
            del request.o_menu[api_num]
        request.o_breadcrumbs = breadcrumbs
